/**
 * Copyright(c) by JNet Smartware Group.
 * All rights reserved. Not distribution or redistribution without
 * any permission of JNet Smartware Group.
 * 
 * @author thuc
 * 2010/03/15
 */
package vn.smartware.co.commons;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CLabel;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.DateTime;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.widgets.Text;
import org.eclipse.wb.swt.SWTResourceManager;

import vn.smartware.co.client.search.SWTCustomerSearch;
import vn.smartware.co.client.search.SWTFoodSearch;
import vn.smartware.co.client.search.SWTRoomSearch;
import vn.smartware.co.dto.MstCustomerDTO;
import vn.smartware.co.dto.MstDrinkDTO;
import vn.smartware.co.dto.MstFoodDTO;
import vn.smartware.co.dto.MstRoomDTO;
import vn.smartware.co.dto.ReserveDto;
import vn.smartware.co.framework.action.Requester;
import vn.smartware.co.framework.bean.AddressDTO;
import vn.smartware.co.framework.bean.CommonItemBean;
import vn.smartware.co.framework.common.BaseConstant;
import vn.smartware.co.framework.exception.ClientException;
import vn.smartware.co.framework.exception.FatalException;
import vn.smartware.co.framework.form.BaseForm;
import vn.smartware.co.framework.form.CommonSearchForm;
import vn.smartware.co.framework.plugin.LangResources;
import vn.smartware.co.framework.utils.MsgBoxUtils;
import vn.smartware.co.java.net.commons.Utils;

/**
 * @author thuctt
 * SWTUtils
 */
public final class SWTUtils {
	
	private static final String TABLE_DEFAULT_SELECTION_LISTENER = "TABLE_DEFAULT_SELECTION_LISTENER";
	
	private static final String TABLE_SELECTION_LISTENER = "TABLE_SELECTION_LISTENER";
	
	private static final String COLOR_BGR_NOT_EDITABLE = "COLOR_BGR_NOT_EDITABLE";
	
	private static final String TEXT_FOCUS_LOST_LISTENER = "TEXT_FOCUS_LOST_LISTENER";
	
	private static final String TEXT_FOCUS_GAINED_LISTENER = "TEXT_FOCUS_GAINED_LISTENER";
	
	private static final String CLABEL_MOUSE_DOWN_LISTENER = "CLABEL_MOUSE_DOWN_LISTENER";
	
	private static final String CLABEL_MOUSE_ENTER_LISTENER = "CLABEL_MOUSE_ENTER_LISTENER";
	
	private static final String CLABEL_MOUSE_EXIT_LISTENER = "CLABEL_MOUSE_EXIT_LISTENER";

	/**
	 * Check processing class
	 * @author thuc
	 *
	 */
	public static class Check {
		
		/**
		 * check NULL or EMPTY of Text control
		 * @param control
		 * @param controlName
		 * @return boolean
		 * @throws ClientException
		 */
		public static boolean checkRequired(Control control, String controlName) throws ClientException {

			if (control instanceof Text) {
				Text text = (Text)control;
				if (Utils.isNullEmpty(text.getText())){
					MsgBoxUtils.errorMsgBox("errors.NOT_NULL", new Object[]{controlName});
					control.setFocus();
					return false;
				}
			} else if (control instanceof CLabel) {
				CLabel text = (CLabel)control;
				if (Utils.isNullEmpty(text.getText())){
					MsgBoxUtils.errorMsgBox("errors.NOT_NULL", new Object[]{controlName});
					control.setFocus();
					return false;
				}
			} else if (control instanceof Combo) {
				Combo text = (Combo)control;
				if (Utils.isNullEmpty(text.getText())){
					MsgBoxUtils.errorMsgBox("errors.NOT_NULL", new Object[]{controlName});
					control.setFocus();
					return false;
				}
			}
			
			return true;
		}
		
		/**
		 * check string only have alpha character or numeric only
		 * @param text
		 * @param control
		 * @return boolean
		 * @throws ClientException
		 */
		public static boolean checkAlphaNummericOnly(Text text, String control) throws ClientException {

			boolean isValid = Utils.isAlphaNummericOnly(text.getText());
			if (!isValid){
				MsgBoxUtils.errorMsgBox("errors.ALPHA_NUMERIC_ONLY", new Object[]{control});
				text.setFocus();
			}
			return isValid;
		}
		
		/**
		 * check string only have alpha character or numeric only
		 * @param text
		 * @param control
		 * @return boolean
		 * @throws ClientException
		 */
		public static boolean checkCharactersOnly(String text, String control) throws ClientException {

			boolean isValid = Utils.isCharactersOnly(text);
			if (!isValid){
				MsgBoxUtils.errorMsgBox("errors.CHARATER_ONLY", new Object[]{control});
			}
			return isValid;
		}
		
		/**
		 * This method checks if the input text contains all numeric
		 * characters.
		 * 
		 * @param text
		 * @param controlName
		 * @return boolean
		 * @throws ClientException
		 */
		public static boolean checkNumeric(Text text, String controlName)
				throws ClientException {
			
			boolean isValid = Utils.isNumeric(Utils.toNormalNumber(text.getText()));
			
			if (!isValid) {
				MsgBoxUtils.errorMsgBox("errors.NUMERIC_FORMAT",
						new Object[] { controlName });
				text.setFocus();
			}
			return isValid;
		}
		
		 /**
		 * This method checks if the input email address is a valid email
		 * addrees.
		 * 
		 * @param text
		 * @param control
		 * @return boolean
		 * @throws ClientException
		 */
		public static boolean checkEmail(Text text, String control)
				throws ClientException {
			
			boolean isValid = false;
			isValid = checkEmail(text.getText(), control);
			if (!isValid){
				text.setFocus();
			}
			return isValid;
		}
		
		/**
		 * This method checks if the input email address is a valid email
		 * addrees.
		 * 
		 * @param text
		 * @param control
		 * @return boolean
		 * @throws ClientException
		 */
		public static boolean checkEmail(String text, String control)
				throws ClientException {
			
			boolean isValid = false;
			String expression = "^[\\w\\.-]+@([\\w\\-]+\\.)+[A-Z]{2,4}$";
			CharSequence inputStr = text;
			// Make the comparison case-insensitive.
			Pattern pattern = Pattern.compile(expression,
					Pattern.CASE_INSENSITIVE);
			Matcher matcher = pattern.matcher(inputStr);
			if (matcher.matches()) {
				isValid = true;
			}
			if (!isValid){
				MsgBoxUtils.errorMsgBox("errors.EMAIL_FORMAT", new Object[]{control});
			}
			return isValid;
		}
		
		/**
		 * check white space in input text
		 * @param text
		 * @param control
		 * @return boolean
		 * @throws ClientException
		 */
		public static boolean checkWhiteSpace(String text, String control)
				throws ClientException {

			boolean isValid = false;
			String expression = "\\s+";
			CharSequence inputStr = text;
			Pattern pattern = Pattern.compile(expression);
			Matcher matcher = pattern.matcher(inputStr);
			if (matcher.matches()) {
				isValid = true;
			}
			if (!isValid) {
				MsgBoxUtils.errorMsgBox("errors.WHITE_SPACE_EXIST",	new Object[] { control });
			}
			return isValid;
		}
		
		/**
		 * check format YYYY/MM/DD
		 * @param text
		 * @param control
		 * @return boolean
		 * @throws ClientException
		 */
		public static boolean checkYYYYMMDDFormat(String text, String control) throws ClientException {
			
			boolean isValid = Utils.isValidDate(text, "yyyy/MM/dd");
			if (!isValid) {
				MsgBoxUtils.errorMsgBox("errors.YMD_FORMAT",	new Object[] { control });
			}
			return isValid;
		}
		
		/**
		 * check format YYYY/MM
		 * @param text
		 * @param control
		 * @return boolean
		 * @throws ClientException
		 */
		public static boolean checkYYYYMMFormat(String text, String control) throws ClientException {
			
			boolean isValid = Utils.isValidDate(text, "yyyy/MM");
			if (!isValid) {
				MsgBoxUtils.errorMsgBox("errors.YM_FORMAT",	new Object[] { control });
			}
			return isValid;
		}

		/**
		 * checkHHMMFormat
		 * @param chktext
		 * @param controlname
		 * @return boolean
		 * @throws ClientException 
		 */
		public static boolean checkHHMMFormat(String chktext, String controlname) throws ClientException {
			
			boolean isValid = Utils.isValidDate(chktext, "HH:mm");
			if (!isValid) {
				MsgBoxUtils.errorMsgBox("errors.HM_FORMAT",	new Object[] { controlname });
			}
			return isValid;
		}

		/**
		 * checkYYYYMMDDBiggerOrEqual (YYYY/MM/DD)
		 * @param text1
		 * @param text2
		 * @param controlName1
		 * @param controlName2 
		 * @return boolean
		 * @throws ClientException
		 */
		public static boolean checkYYYYMMDDBiggerOrEqual(String text1, String text2,
				String controlName1, String controlName2) throws ClientException {
			
			boolean isValid = Utils.compareYYYYMMDD(text1, text2, true);
			if (!isValid) {
				MsgBoxUtils.errorMsgBox("errors.DATE_BIGGER_OR_EQUAL_COMPARE",	new Object[] { controlName1, controlName2 });
			}
			return isValid;
		}
		
		/**
		 * checkHHMMBiggerOrEqual (HH:MM)
		 * @param text1
		 * @param text2
		 * @param controlName1
		 * @param controlName2 
		 * @return boolean
		 * @throws ClientException
		 */
		public static boolean checkHHMMBiggerOrEqual(String text1, String text2,
				String controlName1, String controlName2) throws ClientException {
			
			boolean isValid = Utils.compareHHMM(text1, text2, true);
			if (!isValid) {
				MsgBoxUtils.errorMsgBox("errors.DATE_BIGGER_OR_EQUAL_COMPARE",	new Object[] { controlName1, controlName2 });
			}
			return isValid;
		}
	}
	
	/**
	 * UI Processor
	 * 
	 * @author thuc
	 * 
	 */
	public static class OperatorUI {
		
		/**
		 * set enable/disable Composite
		 * @param comp
		 * @param flg 
		 */
		public static void setEnableAll (Composite comp, boolean flg){
			setEnableAll(comp.getChildren(), flg);
		}
		
		/**
		 * set enable/disable array of controls
		 * @param controls
		 * @param flg
		 */
		public static void setEnableAll(Control[] controls, boolean flg) {

			for (int i = 0; i < controls.length; i++) {
				setEnable(controls[i], flg);
			}
		}

		/**
		 * set enable/disable a control
		 * @param control
		 * @param flg
		 */
		private static void setEnable(Control control, boolean flg) {

			try {
				if (control instanceof Combo || control instanceof DateTime || control instanceof Button) {
					control.setEnabled(flg);

				} else if (control instanceof Table) {
					Table tbl = (Table) control;

					Map<Object, Object> map = new HashMap<Object, Object>();
					map.put(TABLE_DEFAULT_SELECTION_LISTENER, Integer.toString(SWT.DefaultSelection));
					map.put(TABLE_SELECTION_LISTENER, Integer.toString(SWT.Selection));

					removeAllListeners(tbl, map);
					if (flg) {
						addAllListeners(tbl, map);
					}

					if ((tbl.getStyle() & SWT.CHECK) == SWT.CHECK) {
						tbl.setEnabled(flg);
					}

				} else if (control instanceof Text) {
					Text txt = (Text) control;

					Map<Object, Object> map = new HashMap<Object, Object>();
					map.put(TEXT_FOCUS_LOST_LISTENER, Integer.toString(SWT.FocusOut));
					map.put(TEXT_FOCUS_GAINED_LISTENER, Integer.toString(SWT.FocusIn));

					removeAllListeners(txt, map);

					if (flg) {
						addAllListeners(txt, map);
					}

					boolean status = txt.getEditable();
					if (status) {
						if (!flg) {
							Color color = txt.getBackground();
							txt.setData(COLOR_BGR_NOT_EDITABLE, color);
							txt.setBackground(BaseConstant.COLOR_TEXT_BGR_NOT_EDITABLE);
							txt.setEditable(flg);
						}

					} else {
						if (flg) {
							Color color = (Color) txt.getData(COLOR_BGR_NOT_EDITABLE);
							txt.setBackground(color);
							txt.setEditable(flg);
						}
					}

				} else if (control instanceof CLabel) {
					CLabel clbl = (CLabel) control;
					Color fontColor = clbl.getForeground();
					Font font = clbl.getFont();

					if (font.equals(BaseConstant.FONT_LINK_LABEL)) {
						// in present, control is enable
						if (fontColor.equals(BaseConstant.COLOR_LINK_LABEL)) {

							if (!flg) {
								Map<Object, Object> map = new HashMap<Object, Object>();
								map.put(CLABEL_MOUSE_DOWN_LISTENER, Integer.toString(SWT.MouseDown));
								map.put(CLABEL_MOUSE_ENTER_LISTENER, Integer.toString(SWT.MouseEnter));
								map.put(CLABEL_MOUSE_EXIT_LISTENER, Integer.toString(SWT.MouseExit));

								removeAllListeners(clbl, map);
								clbl.setForeground(SWTResourceManager.getColor(
										0, 0, 0));
							}

						} else {// control is disabled
							if (flg) {
								Map<Object, Object> map = new HashMap<Object, Object>();
								map.put(CLABEL_MOUSE_DOWN_LISTENER, Integer.toString(SWT.MouseDown));
								map.put(CLABEL_MOUSE_ENTER_LISTENER, Integer.toString(SWT.MouseEnter));
								map.put(CLABEL_MOUSE_EXIT_LISTENER, Integer.toString(SWT.MouseExit));

								addAllListeners(clbl, map);
								clbl.setForeground(BaseConstant.COLOR_LINK_LABEL);
							}
						}
					}

				} else if (control instanceof Group) {
					Group grp = (Group) control;
					setEnableAll(grp.getChildren(), flg);

				} else if (!(control instanceof Label)
						&& !(control instanceof Composite)) {
					control.setEnabled(flg);

				} else if (control instanceof Composite) {
					setEnableAll(((Composite) control).getChildren(), flg);
				}
				
			} catch (Exception e) {
				e.printStackTrace();
			}
		}

		/**
		 * add all listener of this control
		 * @param control
		 * @param map
		 */
		private static void addAllListeners(Control control, Map<Object, Object> map) {
			for (Object obj : map.keySet()) {
				String key = (String) obj;
				int event = Integer.parseInt((String) map.get(key));
				//
				Listener[] listener = (Listener[])control.getData(key);
				if (null != listener && listener.length > 0){
					for (int j = 0; j < listener.length; j++) {
						control.addListener(event, listener[j]);
					}
				}
			}
		}

		/**
		 * remove all listeners
		 * @param control
		 * @param map
		 */
		private static void removeAllListeners(Control control, Map<Object, Object> map) {
			for (Object obj : map.keySet()) {
				String key = (String) obj;
				int event = Integer.parseInt((String) map.get(key));
				//
				Listener[] listener = (Listener[])control.getData(key);
				if (null != listener && listener.length > 0){
					for (int j = 0; j < listener.length; j++) {
						control.removeListener(event, listener[j]);
					}
				}
			}
		}

		/**
		 * clear action
		 * @param controls
		 */
		public static void clearAll(Control[] controls) {
			
			for (int i = 0; i < controls.length; i++) {
				Control item = controls[i];
				clearControl(item);
			}
		}
		
		/**
		 * clear control
		 * @param item
		 */
		private static void clearControl(Control item) {

			try {
				if (item instanceof Text) {
					Text text = (Text) item;
					text.setText("");
				} 
				else if (item instanceof CLabel) {
					CLabel clbl = (CLabel) item;
					Color bgrColor = clbl.getBackground();
					if (bgrColor.equals(BaseConstant.COLOR_BGR_LABEL)) {
						clbl.setText("");
					}
				} 
				else if (item instanceof Table) {
					Table table = (Table) item;
					table.removeAll();
					String str = (String) table.getData(BaseConstant.TABLE_ROW_COUNT);
					int itemcount = 0;
					if (!Utils.isNullEmpty(str)) {
						itemcount = Integer.parseInt(str);
					}
					if (itemcount > 0) {
						for (int i = 0; i < itemcount; i++) {
							TableItem tblItem = new TableItem(table, SWT.NONE);
							if (i % 2 == 0) {
								tblItem.setBackground(BaseConstant.COLOR_TABLE_ROW_EVEN);
							}
						}
					}
				} 
				else if (item instanceof Combo) {
					Combo cmb = (Combo) item;
					if ((cmb.getStyle() & SWT.READ_ONLY) == SWT.READ_ONLY) {
						cmb.select(0);
					} else if ((cmb.getStyle() & SWT.NONE) == SWT.NONE) {
						cmb.setText("");
					}
				} 
				else if (item instanceof Button) {
					Button btn = (Button) item;
					if ((btn.getStyle() & SWT.CHECK) == SWT.CHECK) {
						btn.setSelection(false);
					}
				}
				else if (item instanceof DateTime) {
					DateTime dt = (DateTime) item;
					SWTUtils.DateTimeProcess.setDefaultDate(dt);
				}
				else if (item instanceof Group) {
					Group group = (Group) item;
					Control[] items = group.getChildren();
					for (int i = 0; i < items.length; i++) {
						Control grpitem = items[i];
						clearControl(grpitem);
					}

				}
				else if (item instanceof Composite) {
					Composite composite = (Composite) item;
					Control[] items = composite.getChildren();
					for (int i = 0; i < items.length; i++) {
						Control compItem = items[i];
						clearControl(compItem);
					}
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		
		/**
		 * format text of a textbox as pattern YYYY/MM/DD
		 * 
		 * @param txt
		 * @return String
		 */
		public static String formatYYYYMMDD(String txt){
			
			int limit = txt.length();
			if (limit < 6){
				return txt;
			}
			
			Date aDate = null;
			
			if (limit == 6) {// YYMMDD
				aDate = Utils.parseDate(txt, "yyMMdd");
				
			} else if (limit == 8) {// YYYYMMDD
				aDate = Utils.parseDate(txt, "yyyyMMdd");
				
			} else {
				return txt;
			}
			
			if (null == aDate){
				return txt;
			}
			
			String retTxt = txt;
			if (null != aDate){
				retTxt = Utils.formatYYYYMMDD(aDate);
			}
			return retTxt;
		}
		
		/**
		 * format text of a textbox as pattern YYYY/MM
		 * 
		 * @param txt
		 * @return String
		 */
		public static String formatYYYYMM(String txt){
			
			int limit = txt.length();
			if (limit < 4){
				return txt;
			}
			
			Date aDate = null;
			
			if (limit == 4) {// YYMM
				aDate = Utils.parseDate(txt, "yyMM");
				
			} else if (limit == 6) {// YYYYMM
				aDate = Utils.parseDate(txt, "yyyyMM");
				
			} else {
				return txt;
			}
			
			if (null != aDate){
				String retTxt = Utils.formatYYYYMM(aDate);
				return retTxt.substring(0, 7);
			}
			return txt;
		}

		/**
		 * format HH:MM
		 * @param text
		 * @return String
		 */
		public static String formatHHMM(String text) {
			
			if (text.length() != 4){
				return text;
			}
			return text.substring(0, 2) + ":" + text.substring(2);
		}
	}
	
	/**
	 * UI Processor
	 * @author thuc
	 *
	 */
	public static class ComboProcess {
		
		/**
		 * return the key ID of an index of line
		 * @param cmb
		 * @param idx
		 * @return String
		 */
		public static String getValue(Combo cmb, int idx){
			List<?> itemList = (List<?>) cmb.getData();
			CommonItemBean item = (CommonItemBean)itemList.get(idx);
			if (item != null) {
				return item.getValue();
			}
			return null;
		}
		
		/**
		 * return the key ID of an index of line
		 * @param cmb
		 * @param key
		 * @return String
		 */
		public static String getLabel(Combo cmb, String key){
			List<?> itemList = (List<?>) cmb.getData();
			for (int i = 0; i < itemList.size(); i++) {
				CommonItemBean item = (CommonItemBean)itemList.get(i);
				if (item != null && item.getValue().equals(key)) {
					return item.getLabel();
				}
			}			
			return "";
		}
		
		/**
		 * return the value name of an index of line
		 * @param cmb
		 * @param idx
		 * @return String
		 */
		public static String getLabel(Combo cmb, int idx){
			List<?> itemList = (List<?>) cmb.getData();
			CommonItemBean item = (CommonItemBean)itemList.get(idx);
			if (item != null) {
				return item.getLabel();
			}
			return "";
		}
		
		/**
		 * return the value name of a selecting line
		 * @param cmb
		 * @return String
		 */
		public static String getSelectingLabel(Combo cmb){
			int selectingIdx = cmb.getSelectionIndex();
			List<?> itemList = (List<?>) cmb.getData();
			CommonItemBean item = (CommonItemBean)itemList.get(selectingIdx);
			if (item != null) {
				return item.getLabel();
			}
			return null;
		}
		
		/**
		 * return the key ID of a selecting line
		 * @param cmb
		 * @return String
		 */
		public static String getSelectingValue(Combo cmb){
			int selectingIdx = cmb.getSelectionIndex();
			List<?> itemList = (List<?>) cmb.getData();
			CommonItemBean item = (CommonItemBean)itemList.get(selectingIdx);
			if (item != null) {
				return item.getValue();
			}
			return null;
		}
		
		/**
		 * set combo select a row which has the same input key
		 * @param cmb
		 * @param key 
		 */
		public static void setDisplayLabel(Combo cmb, String key){
			List<?> itemList = (List<?>) cmb.getData();
			for (int i = 0; i < itemList.size(); i++) {
				CommonItemBean item = (CommonItemBean)itemList.get(i);
				if (item != null && item.getValue().equals(key)){
					cmb.select(i);
					return;
				}
			}
		}
		
		/**
		 * get initialize items data for combobox
		 * 
		 * @param keys
		 * @param combo
		 * @return Map
		 * @throws FatalException
		 */
		public static List<CommonItemBean> getComboItems(Map<Object, Object> keys, Composite composite)
				throws FatalException {

			BaseForm form = new BaseForm();
			form.setMap(keys);
			form.setActionForm("baseForm");
			form.setActionMethod("getComboInitItems");

			form = (BaseForm) Requester.execute(form, composite);

			return form.getItemValueBeanList();
		}
		
		/**
		 * get initialize items data for combobox
		 * 
		 * @param keys
		 * @param combo
		 * @param cmbName
		 * @return Map
		 * @throws FatalException
		 */
		public static void setComboItems(Map<Object, Object> keys, Combo cmb, String cmbName)
				throws FatalException {

			BaseForm form = new BaseForm();
			form.setMap(keys);
			form.setActionForm("baseForm");
			form.setActionMethod("getComboInitItems");

			form = (BaseForm) Requester.execute(form, cmb.getParent());

			List<CommonItemBean> itemsList = form.getItemValueBeanList();
			if (itemsList == null || itemsList.size() == 0){
				MsgBoxUtils.errorMsgBox("errors.COMBO_DATA_NOT_SET",
						new Object[] { cmbName });
				return;
			}
			for (CommonItemBean itemBean : itemsList) {
				cmb.add(LangResources.getText(itemBean.getLabel()));
			}
			cmb.setData(itemsList);
		}
		
		/**
		 * get initialize items data for combobox
		 * 
		 * @param keys
		 * @param shell
		 * @return Map
		 * @throws FatalException
		 */
		public static List<CommonItemBean> getComboItems(Map<Object, Object> keys, Shell shell)
				throws FatalException {

			BaseForm form = new BaseForm();
			form.setMap(keys);
			form.setActionForm("baseForm");
			form.setActionMethod("getComboInitItems");

			form = (BaseForm) Requester.execute(form, shell);

			return form.getItemValueBeanList();
		}
	}
	
	/**
	 * UI Processor for SWT.DateTime
	 * @author thuc
	 *
	 */
	public static class DateTimeProcess {
		
		/**
		 * Set a date to DateTime
		 * @param control
		 * @param date
		 */
		public static void setDate(DateTime control, Date date) {
			if (date == null) {
				return;
			}
			Calendar cal = Calendar.getInstance();
			cal.setTime(date);
			control.setDate(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), cal.get(Calendar.DAY_OF_MONTH));
		}
		
		/**
		 * Set default date
		 * @param control
		 */
		public static void setDefaultDate(DateTime control) {
			Date dt = Utils.parseDate(BaseConstant.DEFAULT_EMPTY_DATE, BaseConstant.FMT_DATE_SHORT);
			setDate(control, dt);
		}
		
		/**
		 * Set default datetime
		 * @param control
		 */
		public static void setDefaultDatetime(DateTime control) {
			Date dt = Utils.parseDate(BaseConstant.DEFAULT_EMPTY_DATE, BaseConstant.FMT_DATE_LONG);
			setDate(control, dt);
		}

		/**
		 * Get a date from DateTime
		 * @param control
		 * @param date
		 */
		public static Date getDate(DateTime control) {
			Calendar cal = Calendar.getInstance();
			cal.set(control.getYear(), control.getMonth(), control.getDay());
			return cal.getTime();
			
		}
	}
	
	/**
	 * Key processor
	 * @author thuc
	 *
	 */
	public static class KeyProcess {
		
		/**
		 * get state mask when press a key CTRL/ALT/SHIFT/COMMAND
		 * @param stateMask
		 * @return Name of Key
		 */
		public static String getKeyStateMask(int stateMask){
			
			if ((stateMask & SWT.CTRL) != 0){
				return Const.KEY_CODE_CTRL;
			}
			if ((stateMask & SWT.ALT) != 0){
				return Const.KEY_CODE_ALT;
			}
			if ((stateMask & SWT.SHIFT) != 0){
				return Const.KEY_CODE_SHIFT;
			}
			if ((stateMask & SWT.COMMAND) != 0){
				return Const.KEY_CODE_COMMAND;
			}
			return "";
		}
		
		/**
		 * get key code
		 * @param keyCode
		 * @return String
		 */
		public static String getKeyCode(int keyCode) {
			
			switch (keyCode) {

			/* Keyboard and Mouse Masks */
			case SWT.ALT:
				return "ALT";
			case SWT.SHIFT:
				return "SHIFT";
			case SWT.CONTROL:
				return "CONTROL";
			case SWT.COMMAND:
				return "COMMAND";

				/* Non-Numeric Keypad Keys */
			case SWT.ARROW_UP:
				return "ARROW_UP";
			case SWT.ARROW_DOWN:
				return "ARROW_DOWN";
			case SWT.ARROW_LEFT:
				return "ARROW_LEFT";
			case SWT.ARROW_RIGHT:
				return "ARROW_RIGHT";
			case SWT.PAGE_UP:
				return "PAGE_UP";
			case SWT.PAGE_DOWN:
				return "PAGE_DOWN";
			case SWT.HOME:
				return "HOME";
			case SWT.END:
				return "END";
			case SWT.INSERT:
				return "INSERT";

				/* Virtual and Ascii Keys */
			case SWT.BS:
				return "BS";
			case SWT.CR:
				return "ENTER";
			case SWT.DEL:
				return "DEL";
			case SWT.ESC:
				return "ESC";
			case SWT.LF:
				return "LF";
			case SWT.TAB:
				return "TAB";

				/* Functions Keys */
			case SWT.F1:
				return "F1";
			case SWT.F2:
				return "F2";
			case SWT.F3:
				return "F3";
			case SWT.F4:
				return "F4";
			case SWT.F5:
				return "F5";
			case SWT.F6:
				return "F6";
			case SWT.F7:
				return "F7";
			case SWT.F8:
				return "F8";
			case SWT.F9:
				return "F9";
			case SWT.F10:
				return "F10";
			case SWT.F11:
				return "F11";
			case SWT.F12:
				return "F12";
			case SWT.F13:
				return "F13";
			case SWT.F14:
				return "F14";
			case SWT.F15:
				return "F15";

				/* Numeric Keypad Keys */
			case SWT.KEYPAD_ADD:
				return "KEYPAD_ADD";
			case SWT.KEYPAD_SUBTRACT:
				return "KEYPAD_SUBTRACT";
			case SWT.KEYPAD_MULTIPLY:
				return "KEYPAD_MULTIPLY";
			case SWT.KEYPAD_DIVIDE:
				return "KEYPAD_DIVIDE";
			case SWT.KEYPAD_DECIMAL:
				return "KEYPAD_DECIMAL";
			case SWT.KEYPAD_CR:
				return "KEYPAD_CR";
			case SWT.KEYPAD_0:
				return "KEYPAD_0";
			case SWT.KEYPAD_1:
				return "KEYPAD_1";
			case SWT.KEYPAD_2:
				return "KEYPAD_2";
			case SWT.KEYPAD_3:
				return "KEYPAD_3";
			case SWT.KEYPAD_4:
				return "KEYPAD_4";
			case SWT.KEYPAD_5:
				return "KEYPAD_5";
			case SWT.KEYPAD_6:
				return "KEYPAD_6";
			case SWT.KEYPAD_7:
				return "KEYPAD_7";
			case SWT.KEYPAD_8:
				return "KEYPAD_8";
			case SWT.KEYPAD_9:
				return "KEYPAD_9";
			case SWT.KEYPAD_EQUAL:
				return "KEYPAD_EQUAL";

				/* Other keys */
			case SWT.CAPS_LOCK:
				return "CAPS_LOCK";
			case SWT.NUM_LOCK:
				return "NUM_LOCK";
			case SWT.SCROLL_LOCK:
				return "SCROLL_LOCK";
			case SWT.PAUSE:
				return "PAUSE";
			case SWT.BREAK:
				return "BREAK";
			case SWT.PRINT_SCREEN:
				return "PRINT_SCREEN";
			case SWT.HELP:
				return "HELP";
			}
			return character((char) keyCode);
		}
		
		private static String character(char character) {
			
			switch (character) {
			case 0:
				return "'\\0'";
			case SWT.BS:
				return "'\\b'";
			case SWT.CR:
				return "'\\r'";
			case SWT.DEL:
				return "DEL";
			case SWT.ESC:
				return "ESC";
			case SWT.LF:
				return "'\\n'";
			case SWT.TAB:
				return "'\\t'";
			}
			return "'" + character + "'";
		}
	}
	
	/**
	 * Processing of open other screen
	 * @author thuctt
	 *
	 */
	public static class SWTControlProcess {
		
		/**
		 * openRoomSearchScreen
		 * @param txtNo
		 * @param clblName
		 * @return MstRoomDTO
		 */
		public static MstRoomDTO openRoomSearchScreen(Text txtNo, CLabel clblName) {
			
			CommonSearchForm searchform = null;
			if (!Utils.isNullEmpty(txtNo.getText())){
				searchform = new CommonSearchForm();
				searchform.setNoStart(txtNo.getText().trim());
			}
			Shell parent = Display.getCurrent().getActiveShell();
			SWTRoomSearch sub = new SWTRoomSearch(parent);
			sub.setSearchCriteria(searchform);
			if (parent.isDisposed()){
				return null;
			}
			MstRoomDTO room = (MstRoomDTO)sub.getResult();
			if (null != room){
				txtNo.setText(room.getRoomNo());
				clblName.setText(room.getRoomName());
			}
			return room;
		}
		
		/**
		 * openRoomSearchScreen
		 * @param txtName
		 * @return MstRoomDTO
		 */
		public static MstRoomDTO openRoomSearchScreen(Text txtName) {
			
			CommonSearchForm searchform = null;
			if (!Utils.isNullEmpty(txtName.getText())){
				searchform = new CommonSearchForm();
				searchform.setName(txtName.getText().trim());
			}
			Shell parent = Display.getCurrent().getActiveShell();
			SWTRoomSearch sub = new SWTRoomSearch(parent);
			sub.setSearchCriteria(searchform);
			if (parent.isDisposed()){
				return null;
			}
			MstRoomDTO room = (MstRoomDTO)sub.getResult();
			if (null != room){
				txtName.setText(room.getRoomName());
			}
			return room;
		}
		
		/**
		 * openRoomSearchScreen
		 * @param txtName
		 * @param autoSearch 
		 * @return MstRoomDTO
		 */
		public static MstRoomDTO openRoomSearchScreen(Text txtName, boolean autoSearch) {
			
			CommonSearchForm searchform = null;
			if (!Utils.isNullEmpty(txtName.getText())){
				searchform = new CommonSearchForm();
				searchform.setName(txtName.getText().trim());
			}
			searchform.setAutoSearch(autoSearch);
			Shell parent = Display.getCurrent().getActiveShell();
			SWTRoomSearch sub = new SWTRoomSearch(parent);
			sub.setSearchCriteria(searchform);
			if (parent.isDisposed()){
				return null;
			}
			MstRoomDTO room = (MstRoomDTO)sub.getResult();
			if (null != room){
				txtName.setText(room.getRoomName());
			}
			return room;
		}

		/**
		 * textRoomNoLostFocusAction
		 * @param txtRoomNo
		 * @param clblRoomName
		 * @return MstRoomDTO
		 */
		public static MstRoomDTO textRoomNoLostFocusAction(Text txtRoomNo,
				CLabel clblRoomName) {
			
			MstRoomDTO room = null;
			try {
				CommonSearchForm form = new CommonSearchForm();
				form.setActionForm("commonSearchForm");
				form.setActionMethod("getRoomList");
				
				form.setNoStart(Utils.toEmpty(txtRoomNo.getText().trim()));
				form.setNoEnd(Utils.toEmpty(txtRoomNo.getText().trim()));
				
				form = (CommonSearchForm)Requester.execute(form);
				
				ArrayList<Object> roomList = form.getList();
				if (roomList != null && !roomList.isEmpty()){
					room = (MstRoomDTO)roomList.get(0);
					if (!Utils.isNullEmpty(room.getRoomName())){
						clblRoomName.setText(room.getRoomName());
					}
				}
				
			} catch (FatalException e) {
				fatalErrorMsgBox();
			}
			
			return room;
		}
		
		/**
		 * textFoodNoLostFocusAction
		 * @param txtNo
		 * @param clblName
		 * @return MstFoodDTO
		 */
		public static MstFoodDTO textFoodNoLostFocusAction(Text txtNo,
				CLabel clblName) {
			
			if (Utils.isNullEmpty(txtNo.getText())){
				return null;
			}
			
			MstFoodDTO food = null;
			try {
				CommonSearchForm form = new CommonSearchForm();
				form.setActionForm("commonSearchForm");
				form.setActionMethod("getFoodList");
				
				form.setNoStart(Utils.toEmpty(txtNo.getText().trim()));
				form.setNoEnd(Utils.toEmpty(txtNo.getText().trim()));
				
				form = (CommonSearchForm)Requester.execute(form);
				
				ArrayList<Object> priceList = form.getList();
				if (priceList != null && !priceList.isEmpty()){
					food = (MstFoodDTO)priceList.get(0);
					if (!Utils.isNullEmpty(food.getName())){
						clblName.setText(food.getName());
					}
				}
				
			} catch (FatalException e) {
				fatalErrorMsgBox();
			}
			
			return food;
		}
		
		/**
		 * textDrinkNoLostFocusAction
		 * @param txtNo
		 * @param clblName
		 * @return MstDrinkDTO
		 */
		public static MstDrinkDTO textDrinkNoLostFocusAction(Text txtNo,
				CLabel clblName) {
			
			if (Utils.isNullEmpty(txtNo.getText())){
				return null;
			}
			MstDrinkDTO drink = null;
			try {
				CommonSearchForm form = new CommonSearchForm();
				form.setActionForm("commonSearchForm");
				form.setActionMethod("getDrinkList");
				
				form.setNoStart(Utils.toEmpty(txtNo.getText().trim()));
				form.setNoEnd(Utils.toEmpty(txtNo.getText().trim()));
				
				form = (CommonSearchForm)Requester.execute(form);
				
				ArrayList<Object> priceList = form.getList();
				if (priceList != null && !priceList.isEmpty()){
					drink = (MstDrinkDTO)priceList.get(0);
					if (!Utils.isNullEmpty(drink.getName())){
						clblName.setText(drink.getName());
					}
				}
				
			} catch (FatalException e) {
				fatalErrorMsgBox();
			}
			
			return drink;
		}

		/**
		 * openFoodSearchScreen
		 * @param txtNo
		 * @param clblName 
		 * @return MstFoodDTO
		 */
		public static MstFoodDTO openFoodSearchScreen(Text txtNo, CLabel clblName) {

			CommonSearchForm searchform = null;
			if (!Utils.isNullEmpty(txtNo.getText())){
				searchform = new CommonSearchForm();
				searchform.setNoStart(txtNo.getText().trim());
			}
			Shell parent = Display.getCurrent().getActiveShell();
			SWTFoodSearch sub = new SWTFoodSearch(parent);
			sub.setSearchCriteria(searchform);
			if (parent.isDisposed()){
				return null;
			}
			MstFoodDTO food = (MstFoodDTO)sub.getResult();
			if (null != food){
				txtNo.setText(food.getFoodNo());
				clblName.setText(food.getName());
			}
			return food;
		}

		/**
		 * Format address
		 * @param address
		 * @return String
		 */
		public static String formatAddress(AddressDTO address) {
			
			String addr = "";
			if (null == address){
				return addr;
			}
			if (!Utils.isNullEmpty(address.getHouseNo())){
				addr += address.getHouseNo() + Const.COMMA;
			}
			if (!Utils.isNullEmpty(address.getStreet())){
				addr += address.getStreet() + Const.COMMA;
			}
			
			String lang = LangResources.getCurrentLanguage();
			if (lang.equals(BaseConstant.VN_LANG_FILE)){
				if (!Utils.isNullEmpty(address.getWard())){
					addr += LangResources.getText("ADDR_WARD") + address.getWard() + Const.COMMA;
				}
				if (!Utils.isNullEmpty(address.getDistrict())){
					addr += LangResources.getText("ADDR_DISTRICT") + address.getDistrict() + Const.COMMA;
				}
				if (!Utils.isNullEmpty(address.getCity())){
					addr += LangResources.getText("ADDR_CITY") + address.getCity();
				}
				
			} else if (lang.equals(BaseConstant.EN_LANG_FILE)){
				if (!Utils.isNullEmpty(address.getWard())){
					addr += address.getWard() + LangResources.getText("ADDR_WARD") + Const.COMMA;
				}
				if (!Utils.isNullEmpty(address.getDistrict())){
					addr += address.getDistrict() + LangResources.getText("ADDR_DISTRICT") + Const.COMMA;
				}
				if (!Utils.isNullEmpty(address.getCity())){
					addr += address.getCity() + LangResources.getText("ADDR_CITY");
				}
			}
			
			return addr;
		}

		/**
		 * openCustomerSearchScreen
		 * @param txtNo
		 * @param clblName
		 * @return MstCustomerDTO
		 */
		public static MstCustomerDTO openCustomerSearchScreen(Text txtNo, CLabel clblName) {
			
			CommonSearchForm searchform = null;
			if (!Utils.isNullEmpty(txtNo.getText())){
				searchform = new CommonSearchForm();
				searchform.setNoStart(txtNo.getText().trim());
			}
			Shell parent = Display.getCurrent().getActiveShell();
			SWTCustomerSearch sub = new SWTCustomerSearch(parent);
			sub.setSearchCriteria(searchform);
			if (parent.isDisposed()){
				return null;
			}
			MstCustomerDTO cus = (MstCustomerDTO)sub.getResult();
			if (null != cus){
				txtNo.setText(cus.getCustomerNo());
				clblName.setText(cus.getName());
			}
			return cus;
		}
		
		/**
		 * openCustomerSearchScreen
		 * @return MstCustomerDTO
		 */
		public static MstCustomerDTO openCustomerSearchScreen() {
			
			CommonSearchForm searchform = null;
			Shell parent = Display.getCurrent().getActiveShell();
			SWTCustomerSearch sub = new SWTCustomerSearch(parent);
			sub.setSearchCriteria(searchform);
			if (parent.isDisposed()){
				return null;
			}
			MstCustomerDTO cus = (MstCustomerDTO)sub.getResult();
			return cus;
		}

		/**
		 * textCustomerNoLostFocus
		 * @param txtNo
		 * @param clblName
		 * @return MstCustomerDTO
		 */
		public static MstCustomerDTO textCustomerNoLostFocus(Text txtNo, CLabel clblName) {
			
			MstCustomerDTO cus = null;
			try {
				CommonSearchForm form = new CommonSearchForm();
				form.setActionForm("commonSearchForm");
				form.setActionMethod("getCustomerList");
				
				form.setNoStart(Utils.toEmpty(txtNo.getText().trim()));
				form.setNoEnd(Utils.toEmpty(txtNo.getText().trim()));
				
				form = (CommonSearchForm)Requester.execute(form);
				
				ArrayList<Object> list = form.getList();
				if (list == null || list.isEmpty()){
					clblName.setText("");
					return cus;
				}
				if (list != null && !list.isEmpty()){
					cus = (MstCustomerDTO)list.get(0);
					if (!Utils.isNullEmpty(cus.getName())){
						clblName.setText(cus.getName());
					}else{
						clblName.setText("");
					}
				}
				
			} catch (FatalException e) {
				fatalErrorMsgBox();
			}
			
			return cus;
		}
		
		/**
		 * calRoomTotalMoney
		 * @param form
		 * @param rentPrice 
		 * @return double
		 */
		public static double calRoomTotalMoney(ReserveDto form, String rentPrice) {
			
			double total = 0;
			String startDay = form.getInuseYmd().replaceAll("/", "");
			String[] time = form.getInuseTime().split(":", -1);
			double startTime = Integer.parseInt(time[0]) + Double.parseDouble(time[1])/60;
			String endDay = form.getFinishYmd().replaceAll("/", "");
			time = form.getFinishTime().split(":", -1);
			double endTme = Integer.parseInt(time[0]) + Double.parseDouble(time[1])/60;
			int totalDay = Integer.parseInt(endDay) - Integer.parseInt(startDay);
			double totalTime = endTme - startTime;
			double price = 0;
			if (!Utils.isNullEmpty(rentPrice)){
				price = Double.parseDouble(Utils.toNormalNumber(rentPrice));
			}
			
			String rentType = form.getRentType();
			if (rentType.equals(Const.SYSTEM_CONFIG.RENT_TYPE_BY_HOUR)) {
				total = (totalDay * 24 + totalTime) * price ;
				
			} else if (rentType.equals(Const.SYSTEM_CONFIG.RENT_TYPE_BY_NIGHT)) {
				
			} else {
				
			}
			
			return total;
		}
	}
	
	/**
	 * fatalErrorMsgBox
	 */
	private static final void fatalErrorMsgBox() {
		
		try {
			MsgBoxUtils.errorMsgBox("errors.SYSTEM_ERROR", new Object[] {});
		} catch (ClientException ce) {
			ce.printStackTrace();
		}
	}
	
}
